home *** CD-ROM | disk | FTP | other *** search
- ;-------------------------mbindiv routine begins--------------------------+
- ; from BLUEBOOK OF ASSEMBLY ROUTINES FOR IBM PC & XT.
- ; page : 122
- ;
- ; NAME MBINDIV
- ;
- ; ROUTINE FOR Multidigit Binary DIVISION
- ;
- ; FUNCTION: This routine divides two multidigit binary numbers, producing
- ; both a quotient and remainder.
- ;
- ; INPUT: Upon entry DS:SI points to the divisor; DS:BX points to where
- ; the dividend is upon entry and where the remainder will be upon exit,
- ; and DS:DI points to the location where the quotient will be upon exit.
- ; The size of these multidigit numbers is controlled by the constant
- ; ISIZE. The divisor and quotient contain 16*ISIZE number of
- ; bits and the dividend and remainder have double that precision.
- ; Both the divisor and the quotient are stored in ISIZE number of 16-bit
- ; words of memory and the dividend and remainder are stored in 2*ISIZE
- ; number of 16-bit words of memory.
- ;
- ; OUTPUT: Upon exit DS:BX points to where the quotient is stored and
- ; DS:DI points to where the remainder is stored.
- ;
- ; REGISTERS USED: No registers are modified.
- ;
- ; SEGMENTS REFERENCED: Upon entry the data segment must contain
- ; storage for the multidigit numbers described above.
- ;
- ; ROUTINES CALLED: None
- ;
- ; SPECIAL NOTES: None
- ;
- ; LOCAL SUBROUTINE TO COMPARE DIVISOR AGAINST DIVIDEND
- ;
- divcmp proc near
- ;
- push si ; save registers
- push di
- push cx
- ;
- std ; backward direction
- add si,4*isize-2 ; point to end of temp divisor
- add di,4*isize-2 ; point to end of quotient
- mov cx,2*isize ; count for double precision
- ;
- repz cmpsw ; compare 'digit' by 'digit'
- ;
- pop cx ; restore registers
- pop di
- poop si
- ret ; return from divcmp
- ;
- ; LOCAL SUBROUTINE FOR ARITHMETIC SHIFT DIVISOR LEFT
- ;
- divsal proc near
- ;
- push si ; save registers
- push cx
- ;
- mov cx,2*isize ; set counter
- clc ; clear carry in
- ;
- divsal1:
- rcl word ptr [si],1 ; shift one word by one bit
- inc si ; point to next word
- inc si
- loop divsal1 ; loop through entire divisor
- ;
- pop cx ; restore registers
- pop si
- ret ; return from divsal
- ;
- divsal endp
- ;
- ; LOCAL SUBROUTINE FOR LOGICAL SHIFT DIVISOR RIGHT
- ;
- divslr proc near
- ;
- push si ; save registers
- push cx
- ;
- add si,4*isize-2 ; poin to end of temp divisor
- mov cx,2*isize ; count for double precision
- clc ; clear carry in
- ;
- divslr1:
- rcr word ptr [si],1 ; shift one word by one bit
- inc si ; point to next word
- inc si
- loop divslr1 ; loop through entire divisor
- ;
- pop cx ; restore registers
- pop si
- ret ; return from divslr
- ;
- divslr endp
- ;
- ; LOCAL SUBROUTINE TO SUBTRACT SHIFTED DIVISOR FROM DIVIDEND
- ;
- divsub proc near
- ;
- push si ; save registers
- push di
- push cx
- ;
- clc ; clear carry in
- mov cx,2*isize ; set count fop double precision
- ;
- divsub1:
- mov ax,[si] ; get word from shifted divisor
- inc si ; point to next word
- inc si
- sbb [di],ax ; subtract from word of dividend
- inc di ; point to next word
- inc di
- loop divsub1 ; loop through all words
- ;
- pop cx
- pop di
- pop si
- ;
- ret ; return from divsub
- ;
- divsub endp
- ;
- ; LOCAL SUBROUTINE TO SHIFT QUOTIENT LEFT
- ;
- quotshl proc near
- ;
- push bx ; save registers
- push cx
- ;
- mov cx,isize ; count for single precision
- ;
- quotshl1:
- rcl word ptr [bx],1 ; shift word of quotient left once
- inc bx ; point to next word
- inc bx
- loop quotshl1 ; loop through entire quotient
- ;
- pop cx ; restore registers
- pop bx
- ret ; retirn from quotshl
- ;
- quotshl endp
- ;
- ; ROUTINE TO DIVIDE MULTIDIGIT BINARY NUMBERS
- ;
- mbindiv proc far
- ;
- push si ; save registers
- push di
- push bx
- push cx
- push ax
- ;
- ; put single precision divisor into double precision location
- push di ; save dividend pointer
- lea di,tempdiv ; point to temporary divisor
- mov cx,isize ; for a count of isize
- cld ; forward direction
- rep movsw ; make the transfer
- ;
- ; clear upper part of double precision location
- mov ax,0 ; zero word
- mov cx,isize ; for a count of isize
- rep stosw ; clear the rest of the words
- ;
- ; restore dividend pointer and point to temp divisor
- pop di ; restore dividend pointer
- lea si,tempdiv ; point SI to temporary divisor
- ;
- ; initialize shift count
- mov cx,1 ; initial count of one
- ;
- ; normalize divisor
- mbindiv1:
- test msbdiv,8000h ; test msb of divisor
- jnz mbindiv2 ; exit if normalized
- call divsal ; arithmetic shift if not
- inc cx ; count the shift
- jmp mbindiv1 ; keep on looping until normalized
- ;
- ; compare, subtract, shift loop
- mbindiv2:
- call divcmp ; compare divisor against dividend
- ja mbindiv3 ; skip if too large
- call divsub ; subtract if OK
- stc ; new bit of quotient is 1
- jmp mbindiv4 ; jump to end of loop
- ;
- mbindiv3:
- clc ; new bit of quotient is 0
- ;
- mbindiv4:
- call quotshl ; shift bit into the quotient
- call divslr ; logical shift divisor right once
- loop mbindiv2 ; loop for next digit
- ;
- pop ax ; restore registers
- pop cx
- pop bx
- pop di
- pop si
- ;
- mbindiv endp
- ;-------------------------mbindiv routine ends---------------------------